//
//  main.cpp
//  CPP
//
//  Created by wangrui on 14-5-4.
//  Copyright (c) 2014年 PPS. All rights reserved.
//

#include <iostream>

class InnerClass
{
public:
    void description()
    {
        std::cout<< " InnerClass "<< std::endl;
    }
};


class A
{
public:
    typedef int MYINT;
    
    typedef InnerClass InnerClass;
    
    void description()
    {
        std::cout<< " A "<< std::endl;
    }
};

class B
{
public:
    int qualifier;
    
    void description()
    {
        std::cout<< " B "<< std::endl;
    }
};


struct C
{
    void description() //struct 默认 为 public的
    {
        std::cout<< " C "<< std::endl;
    }
};



template <class aT, class bT,typename cT>
class Test {
    
    aT a;
    bT b;
    cT c;

public:
    typedef aT anotherA;
    
    anotherA aa;
    //typedef aa myaa; 报错
    
    void description()
    {
        a.description();
        b.description();
        c.description();
    };
    
};


//要声明在模板类之后，模板类作为友元类才不会报错
struct D
{
    
public:
    int qualifier;
    friend class Test<A, B, D>;//这时，则要Test<A, B, D>为这种模板的才能访问
    
private:
    void description()
    {
        std::cout<< " D "<< std::endl;
    }
};


template <class T>
class Test2 {

public:
    
    T t;
    typename T::MYINT at; //表示MYINT是T中定义的一种类型， at是这种类型的一个对象. 不加 typename 表示是一个静态变量
    typedef typename T::InnerClass IC;//定义 T中定义了的InnerClass为 IC类型

    IC ic;
    
    void description()
    {
        t.description();
        ic.description();
        std::cout<<" "<< at << std::endl;
        
    };
};


int main(int argc, const char * argv[])
{
    std::cout<<" ========================== class keyword ==============================="<<std::endl;
    Test<C, B, A> t1;// 说明 class 关键字并不是要真正给一个类进去，这时 class 和 typename 一模一样的作用，就表示它是一个模板
    t1.description();

//    Test<float, double, long> t3; //编译器报错，编译器会检查传进去的类模板能不能响应 description() 函数,把其他类的description函数改成private也不行
//    t3.description();             //只能声明为友元类才能访问

    
//    Test<C, D, A> t2; // 编译报错，不能访问私有函数。Test<C, D, A>这种模板类不是 D 的友元类
//    t2.description();
    
    std::cout<<" ========================== friend class and template test ==============================="<<std::endl;
    Test<A, B, D> t2;//Test<A, B, D>模板类是 D 的友元类，可以访问
    t2.description();
    

    //typename test
    std::cout<<" ========================== typename test ==============================="<<std::endl;
    Test<A, B, D> t3;
    t3.aa.description();
    
    
    Test2<A> t4;
    t4.at = 5;
    t4.description();
    
    return 0;
}

